import './style/index.less';
import webglUtils from './ThirdParty/webgl-utils';
import * as dat from 'dat.gui';

import VS from './Shaders/demo5VS.glsl';
import FS from './Shaders/demo5FS.glsl';

const m3 = {
    projection: (width, height) => {
        return [
            2 / width, 0, 0,
            0, -2 / height, 0,
            -1, 1, 1,
        ]
    },
    translation: (tx, ty) => {
        return [
            1, 0, 0,
            0, 1, 0,
            tx, ty, 1,
        ];
    },
    rotation: (angleInRadians) => {
        var c = Math.cos(angleInRadians);
        var s = Math.sin(angleInRadians);
        return [
            c, -s, 0,
            s, c, 0,
            0, 0, 1,
        ];
    },
    scaling: (sx, sy) => {
        return [
            sx, 0, 0,
            0, sy, 0,
            0, 0, 1,
        ];
    },
    multiply: (a, b) => {
        var a00 = a[0 * 3 + 0];
        var a01 = a[0 * 3 + 1];
        var a02 = a[0 * 3 + 2];
        var a10 = a[1 * 3 + 0];
        var a11 = a[1 * 3 + 1];
        var a12 = a[1 * 3 + 2];
        var a20 = a[2 * 3 + 0];
        var a21 = a[2 * 3 + 1];
        var a22 = a[2 * 3 + 2];
        var b00 = b[0 * 3 + 0];
        var b01 = b[0 * 3 + 1];
        var b02 = b[0 * 3 + 2];
        var b10 = b[1 * 3 + 0];
        var b11 = b[1 * 3 + 1];
        var b12 = b[1 * 3 + 2];
        var b20 = b[2 * 3 + 0];
        var b21 = b[2 * 3 + 1];
        var b22 = b[2 * 3 + 2];
        return [
            b00 * a00 + b01 * a10 + b02 * a20,
            b00 * a01 + b01 * a11 + b02 * a21,
            b00 * a02 + b01 * a12 + b02 * a22,
            b10 * a00 + b11 * a10 + b12 * a20,
            b10 * a01 + b11 * a11 + b12 * a21,
            b10 * a02 + b11 * a12 + b12 * a22,
            b20 * a00 + b21 * a10 + b22 * a20,
            b20 * a01 + b21 * a11 + b22 * a21,
            b20 * a02 + b21 * a12 + b22 * a22,
        ];
    },
    translate: function (m, tx, ty) {
        return m3.multiply(m, m3.translation(tx, ty));
    },

    rotate: function (m, angleInRadians) {
        return m3.multiply(m, m3.rotation(angleInRadians));
    },

    scale: function (m, sx, sy) {
        return m3.multiply(m, m3.scaling(sx, sy));
    },
}

function render() {
    const canvas = document.getElementById("canvas");
    const gl = canvas.getContext('webgl2');
    if (!gl) {
        console.log('webgl2 not supported');
    }

    const program = webglUtils.createProgramFromSources(gl, [VS, FS]);

    //attribute和uniform的位置
    const positionAttributeLocation = gl.getAttribLocation(program, "a_position");

    //attribute的状态
    const vao = gl.createVertexArray();
    //关联当前使用这个vao
    gl.bindVertexArray(vao);

    //创建position数据的buffer
    const positionBuffer = gl.createBuffer();
    //启用position attribute
    gl.enableVertexAttribArray(positionAttributeLocation);
    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

    //告诉attribute如何从positionBuffer读取数据
    const size1 = 2;
    const type1 = gl.FLOAT;
    const normalize1 = false;
    const stride1 = 0;
    const offset1 = 0;
    gl.vertexAttribPointer(positionAttributeLocation, size1, type1, normalize1, stride1, offset1);

    //激活position buffer，在setRectangle中用
    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
    //设置画框（两个三角形）的position
    setRectangle(gl, 0, 0, 100, 50);

    //调整分辨率与canvas大小相等
    webglUtils.resizeCanvasToDisplaySize(gl.canvas);
    //调整webgl画布大小与canvas大小相等
    gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
    gl.clearColor(0, 0, 0, 0);
    gl.clear(gl.COLOR_BUFFER_BIT);

    //使用创建的以上的program
    gl.useProgram(program);

    function redraw() {
        //调整webgl画布大小与canvas大小相等
        // gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
        // gl.clearColor(0, 0, 0, 0);
        gl.clear(gl.COLOR_BUFFER_BIT);

        //更新矩阵
        updateMatrix();
        gl.uniformMatrix3fv(matrixUniformLocation, false, matrix);

        //绘制方形画布
        const primitiveType = gl.TRIANGLES;
        const offset3 = 0;
        const count = 6;
        gl.drawArrays(primitiveType, offset3, count);
    }

    let matrix;
    function updateMatrix(){
        let angleInDegrees = 360 - mat.angle;
        let angleInRadians = angleInDegrees * Math.PI / 180;
        //计算矩阵
        matrix = m3.projection(gl.canvas.clientWidth, gl.canvas.clientHeight);
        matrix = m3.translate(matrix, mat.x, mat.y);
        matrix = m3.rotate(matrix, angleInRadians);
        matrix = m3.scale(matrix, mat.sx, mat.sy);
        return matrix;
    }

    /**
     * 设置UI和事件
     */
    const gui = new dat.GUI();
    const mat = {
        x: 0,
        y: 0,
        sx: 1,
        sy: 1,
        angle:0
    };

    const x = gui.add(mat, 'x', 0, 1000);
    const y = gui.add(mat, 'y', 0, 800);
    const sx = gui.add(mat, 'sx', 1, 10);
    const sy = gui.add(mat, 'sy', 1, 10);
    const angle = gui.add(mat, 'angle', 0, 360);
    x.onChange((value) => {
        // mat.x = value;
        redraw();
    });
    y.onChange((value) => {
        // mat.y = value;
        redraw();
    });

    sx.onChange((value) => {
        // mat.sx = value;
        redraw();
    });
    sy.onChange((value) => {
        // mat.sy = value;
        redraw();
    });
    angle.onChange((value) => {
        redraw();
    });

    //声明uniform
    const matrixUniformLocation = gl.getUniformLocation(program, "u_matrix");
    const colorUniformLocation = gl.getUniformLocation(program, "u_color");
    //传入uniform
    gl.uniform4f(colorUniformLocation, 1, 0, 0, 1);
    //更新矩阵
    updateMatrix();
    gl.uniformMatrix3fv(matrixUniformLocation, false, matrix);

    //绘制方形画布
    const primitiveType = gl.TRIANGLES;
    const offset3 = 0;
    const count = 6;
    gl.drawArrays(primitiveType, offset3, count);
}



function setRectangle(gl, x, y, width, height) {
    var x1 = x;
    var x2 = x + width;
    var y1 = y;
    var y2 = y + height;
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
        x1, y1,
        x2, y1,
        x1, y2,
        x1, y2,
        x2, y1,
        x2, y2,
    ]), gl.STATIC_DRAW);
}

render();